;
class SceneEvent {

	_api;
	_sceneName;
	_abPath;
	_canvas;
	_builds;
	_currentBuild;
	_currentFlos;
	_devices;
	_t;
	_ctx;
	_ctxVideo;
	//顶部弹窗 .success("")  .error("")
	_elMsg;

	_gameInstance;
	#sql;
	#deviceTypeIsDone; //类型是否已初始化

	_host = 'http://115.29.53.188'; // 'http://192.168.1.252';//'192.169.20.40';
	_host2 = 'http://115.29.53.188';
	//let host = "http://192.168.1.252"; //"http://115.29.53.188";//
	//(host + ':8096/Admin/CS/ServerAPIData.ashx')
	constructor({
		api,
		elMsg,
		canvas,
		abPath,
		sceneName
	}) {

		let u = this._host + ':8096/Admin/CS/ServerAPIData.ashx'; //
		this._api = api(u); //
		this._elMsg = elMsg;
		window.hGetBase64 = (id) => {
			return this.hGetBase64(id);
		}
		window.__hFromUinty = (t) => {
			this.#hEvent(t);
		}
		/*window.__hFromUinty =  this.#hEvent(t);
		this.#hEvent 中的this将指向空
		*/

		this.#deviceTypeIsDone = false;
		this._t = -1;

		this._sceneName = sceneName;
		this._canvas = canvas;
		this._abPath = abPath || `lib/uwebgl/StreamingAssets`;
		console.log(arguments, abPath, this._abPath, sceneName);
		var script = document.createElement("script");
		script.src = `lib/uwebgl/Build/${sceneName}.loader.js`;
		script.setAttribute("type", "text/javascript");
		script.onload = () => {
			this.#hInitScene();
		};
		document.body.appendChild(script);
	}
	/**初始化场景
	 * 
	 */
	#hInitScene() {
		// 1073741824;B-KB-MB-GB
		var s1GB = 1* (1 * 1024) * (1 * 1024) * (1024 * 1);
		var config = {
			TOTAL_MEMORY: s1GB ,
			dataUrl: `lib/uwebgl/Build/${this._sceneName}.data`,
			frameworkUrl: `lib/uwebgl/Build/${this._sceneName}.framework.js`,
			codeUrl: `lib/uwebgl/Build/${this._sceneName}.wasm`,
			streamingAssetsUrl: this._abPath,
			companyName: "久道信息",
			productName: "Base-URP",
			productVersion: "0.1",
			showBanner: () => {},
		};
		if (/iPhone|iPad|iPod|Android/i.test(navigator.userAgent)) {
			// Avoid draining fillrate performance on mobile devices,
			// and default/override low DPI mode on mobile browsers.
			config.devicePixelRatio = 1;
			console.warn("移动设备不支持WebGL构建");

		}

		/**
		 * 2020.3.36f1c1
		 */
		createUnityInstance(this._canvas, config, (progress) => {
			this.OnInitProcess(progress);
		}).then((unityInstance) => {
			this._gameInstance = unityInstance;
			//加载完成
			setTimeout(() => {
				this.OnInitDone();


			}, 2000);
		}).catch((message) => {
			this._elMsg.error(message);
		});

	}

	hApiGetSelect(sql, back) {
		let dat = `?typeId=3&data=${sql}`;
		this._api.hDoGet(null, dat, back);
	}

	hApiPostSelect(sql, back) {
		let dat = {
			typeId: 3,
			data: sql
		};
		this._api.hDoPost(null, null, dat, back);
	}
	//更新数据get
	hApiGetUpdata(sql, back) {
		let url = this._host + "GetDataAPI.ashx";
		let dat = `?title=CtrlTable&data=${sql}`;
		this._api.hDoGet(url, dat, back);
	};
	//更新数据post
	hApiPostUpdata(sql, back) {
		let dat = {
			title: 'CtrlTable',
			data: sql
		};
		let url = this._host + "GetDataAPI.ashx";
		this._api.hDoPost(url, null, dat, back);
	}


	/**初始化场景进度
	 * @param {Object} t  0~1
	 */
	OnInitProcess(t) {
		console.log("载入：", t);
	}

	/**当场景准备就绪
	 * 
	 */
	OnInitDone() {
		console.log("场景准备就绪");
		console.log("GetCurentBuildPos获取当前的楼宇");
		let pv = {
			m_use: true,
			m_bName: "",
			m_Pos: "{x:10.6274,y:4.954372,z:158.6504}",
			m_Rot: "{x:4.565123,y:177.6,z:-1.177675e-06}"
		};
		this.SetCurrentBuildPos(pv);
		this.hInEvent("SetCurrentBuild", '');
	}

	/**当前场景的所有楼宇 sceneready-1    deviceType-1
	 * @param {Object} builds 
	 */
	// OnSceneDone(builds) {
	// 	this._builds = eval(builds);
	// 	console.log("当前场景的所有楼宇。", this._builds);
	//
	//
	// }


	hJsApi(cmd, dat, cback) {
		return {
			mHandle: cmd || '', //场景内函数
			mCallback: cback || '', //回调函数
			mJson: dat || '' //参数
		}
	}

	/**调用场景
	 * @param {Object} h   内部方法
	 * @param {Object} d	参数
	 * @param {Object} bh	回调
	 */
	hInEvent(h, d, bh) {
		var json = JSON.stringify(this.hJsApi(h, d, bh));
		console.log("call:", json);
		this._gameInstance.SendMessage("WebGL", "hCall", json);
	}

	/**事件分发
	 * @param {Object} json 
	 */
	#hEvent(json) {
		var dat;
		if (json?.length <= 0) {
			console.warn("返回数据异常", json);
			return;
		}
		try {
			json = json.replace(/\r|\n|\t|\\{1,}t|\\{1,}r|\\{1,}n/gi, "");
			//json.replace(/[\n\t\r]/gi, "").replace(/[\\]/gi, "");

			//			json = json.replaceAll('\"', '').replaceAll('\\', '');

			dat = eval("[" + json + "]");
			if (dat.length != 1) {
				console.warn("返回数据格式异常，非json。", json);
				return;
			}
		} catch (e) {
			console.warn("返回数据格式转换异常。", json, e);
			return;
			//TODO handle the exception
		}
		dat = dat[0];
		var hCall = dat.mCallback;

		//此调用方法内的this指向空
		//var fn = this[hCall];
		//fn(dat.mJson)

		if (this[hCall]) {
			let d = dat.mJson;
			try {
				d = eval(`[${d}]`);
				d = d[0];
			} catch (e) {
				d = dat.mJson;
			}
			this[hCall](d);
		} else {
			this.OnOther(dat);
		}
	}

	/**当其它
	 * @param {Object} d
	 */
	OnOther(d) {
		console.log("其它数据。", d);
	}

 

	//-----------------------------   事件传出（主动）  -------------------/
	/**当资源下载进度
	 * @param {Object} dinfo 
	 */
	OnDownLoadProgress(dinfo) {
		hLoadingProcess(eval(dinfo)[0]);
	}

	/**当前旋转角度 指南针角度
	 * @param {Object} angle 角度
	 */
	OnRotate(angle) {
		//__vStore.state.datRot = -angle;
		//console.log("旋转角度。", angle);
	}

	/**锁定旋转操作
	 * @param {Object} isLock
	 */
	SetLockRot(isLock) {
		this.hInEvent("SetLockRot", isLock);
	}

	/**当前楼宇的所有楼层
	 * @param {Object} flos
	 */
	OnBuildChaged(flos) {
		flos = eval(flos);
		this._currentFlos = flos;
		console.log("当前楼宇的所有楼层。", flos);
	}



	/**当右键双击
	 * @param {Object} d 
	 */
	OnClickDbR(d) {
		console.log("db r", d);

	}


	_lastCamDecal;
	/**当左键双击
	 * @param {Object} d 
	 */
	OnClickDbL(d) {

		console.log("左键双击", d);
		//PlayVideo(d.ID, d.SXTJSON, '122.224.55.29');

	}
	/**当右键击
	 * @param {Object} d 
	 */
	OnClickR(d) {
		console.log("r", d);
	}
	/**当左键击
	 * @param {Object} d 
	 */
	OnClickL(d) {
		console.log("l", d);

	}


	//------------------- ---------- 登录--------------------------------/  
	/** 请求登录
	 * @param {Object} user  login-1
	 */
	Login(user) {
		//console.log("登录1：", user);
		this.hInEvent("Login", user, "OnGetLogin");
	}

	/**远程登录验证语句
	 * @param {Object} sql  login-2
	 */
	OnGetLogin(sql) {
		let dat = `?typeId=3&data=${sql}`;
		this._api.hLogin(dat, (user) => {
			if (user.result) {
				//console.log("登录2：", user);
				this.hInEvent("SetUser", user.dat, "OnUserScene");

				this._elMsg.success("登录成功-加载类型" + user.dat?.name);
				console.log("登录成功-加载类型：", user);
				this.OnUserLogind();
				this.DeviceTypeMain();
			} else {
				this._elMsg.error("登录失败" + JSON.stringify(user));
				console.warn("登录失败：", dat, user);
			}
		});
	}

	hMsg(msg) {
		this._elMsg.success(msg);
	}
	/**当登录成功
	 * @param {Object} user  login-3 end scene-1
	 */
	OnUserLogind(user) {}

	/** 请求设备类型
	 *  deviceType-1
	 */
	DeviceTypeMain() {
		//deivceType [0] 开始  
		this.hInEvent("DeviceTypeMain", "", "InitDeviceMain");
	}

	/**查询设备主类型 
	 * @param {Object} sql deviceType-1
	 */
	InitDeviceMain(sql) {
		//deivceType [1]
		if (sql.length < 6) {
			console.log("查询主类型失败，后台返回异常:", sql);
			return;
		}
		//console.log("查询主类型 :", sql);
		this.hApiGetSelect(sql, (t) => {

			//deviceType-3
			console.log("设置设备主类型 :", t);
			this.hInEvent("SetDeviceTypeMain", t, "InitDeviceSub");
		});
	}
	/**查询设备子类型
	 * @param {Object} sql deviceType-4
	 */
	InitDeviceSub(sql) {
		//deivceType [3]
		//console.log("查询子类型 :", sql);
		this.hApiGetSelect(sql, (t) => {

			//deviceType-5  end
			console.log("设置设备子类型 :", t);
			this.hInEvent("SetDeviceTypeSub", t);
			this.#deviceTypeIsDone = true;
		});
	}


	//------------------- ----------场景模型准备--------------------------------/
	/** 场景关系语句
	 * @param {Object} sql   scene-2
	 */
	OnUserScene(sql) {
		this.hApiGetSelect(sql, (uscene) => {
			if (uscene.length > 0) {
				uscene = uscene[0];
			}
			console.log("UserScene:", uscene);

			this.hInEvent("SetUserScene", uscene, "OnInitScene");
		});
	}

	/** 初始化场景
	 * @param {Object} sql  scene-4
	 */
	OnInitScene(sql) {
		this.hApiGetSelect(sql, (dat) => {
			if (dat.length > 0) {
				dat = dat[0];
			}
			console.log("scene:", dat);
			this.hInEvent("SetScene", dat, "OnModSql");
		});
	}

	/** 场景设备查询按需初始化模板资源
	 * @param {Object} sql device-2
	 */
	OnModSql(sql) {

		if (!sql) {
			console.warn("未加载设备", sql);
			return;
		}
		//按需初始化模板资源
		var sqlgroup = `${sql.replace(" * ", " modelName ")} group by modelName`;
		this.hApiGetSelect(sqlgroup, (t) => {
			if (t.length <= 0) {
				let m = "模板初始化。当前场景未添加任何设备...";
				console.log(m);
				this.hMsg(m);
				return;
			}
			console.log("模板初始化:", t);
			this.hInEvent("SetProjDevTemplate", t);
		});
		this.#sql = sql;

	}
	/**模板加载完成
	 * 
	 */
	OnDevTemplateDone() {
		console.log("模板初始化完成,初始化设备...");

		this.InitDevices();
	}



	/**开始初始化设备
	 * 
	 */
	InitDevices() {

		var sql = this.#sql;
		if (this._builds && sql) {

		} else {
			setTimeout(() => {
				this.InitDevices();
			}, 1000)
			return;
		}

		var all = 100;

		//数据大小/页
		var _datPck = 150;
		//总数
		var sqlcount = sql.replace(" * ", " count(*) AS count ");
		console.log("初始化设备", sqlcount);

		this.hApiGetSelect(sqlcount, (dct) => {
			all = +(dct[0]?.count);

			//页数
			var pkgs = Math.ceil(all / _datPck);

			console.log(`count:【${all}】,pkgsize:【${_datPck}】pkgs:【${pkgs}】`);

			for (var i = 0; i < pkgs; i++) {

				var pkgsql = `${sql} limit ${i * _datPck},${_datPck}`;
				this.hApiGetSelect(pkgsql, (t) => {
					console.log("devices json", t);
					this.hInEvent("SetDevices", t);
				});
			}

		});
	}

	/**当所有设备载入结束
	 * 
	 */
	OnDevLoadDone() {
		//所有设备加载完成

		if (this._t) {
			clearTimeout(this._t);
		}
		this._t = setTimeout(() => {
			console.log("----------------所有设备已加载----------------------------");
			clearTimeout(this._t);
			this.GetDeviceAll(true);
		}, 1000);
	}

	/**获取所有初始化成功的设备
	 * @param {Object} v v=true 所有设备，v=fale 仅可见设备
	 */
	GetDeviceAll(v) {
		console.log("获取所有加载的设备");
		this.hInEvent("GetDeviceAll", v, "OnDeviceAllDat");
	}
	/**所有载入成功的设备
	 * @param {Object} all
	 */
	OnDeviceAllDat(all) {
		/**返回设备字段
		    d.Name 
            d.modelType  --subTypeId
            d.typeId  --mainTypeId
            d.ID 
		 * */
		this._devices = eval(all);
		console.log(" 所有设备", this._devices);
		this.OnDoneDevice(this._devices);
	}

	OnDoneDevice(d) {}


	/**消防水管
	 * @param {Object} v
	 */
	OnXfsg(v) {
		console.log("水管", v);
	}
	GetXfsg() {

		this.hInEvent("GetXfsg", '', "OnXfsg");
	}

	/**楼梯电梯
	 * @param {Object} v
	 */
	OnLouTi(v) {
		console.log("楼梯", v);
	}
	GetLouTi() {

		this.hInEvent("GetLouTi", '', "OnLouTi");
	}

	/**防范页面
	 * @param {Object} v true:改变楼梯电梯颜色，false:恢复颜色
	 */
	SetSecurity(v) {
		this.hInEvent("SetSecurity", v);
	}

	/**设备灯光开关
	 * @param {Object} v
	 * 
	 * 场景内id（惟一） gameObjectId
	 * int gId = -1; 
	 * 数据Id（惟一） dev datID
	 * int datId = -1;
	 * r红,g绿,b蓝,y黄   (0关,1开)
	 */
	OpenLight(v) {
//		console.log("灯光开启",v);
		this.hInEvent("OpenLight", v);
	}

	//================----------场景-----------=============
	/**场景灯光开关
	 * @param {Object} v
	 */
	SetLight(v) {
		//灯光开关 bool  true or false
		this.hInEvent("SetLight", v);
	}

	/**灯光亮强度设置
	 * @param {Object} v
	 */
	SetLightValue(v) {
		//灯光亮度调节 float 
		this.hInEvent("SetLightValue", v);
	}

	/**跳转到主页
	 * 
	 */
	SetToHome() {
		//console.log("return home:");
		this.SetBuild();
	}

	/**显示外场景
	 * @param {Object} v
	 */
	//顯示外場
	SetBaseShow(v) {
		console.log("显示外场景", v);
		this.hInEvent("SetBaseShow", v);
	}

	/**缩放限制设置
	 * @param {Object} t
	 * {enable:true/false,min:0,max:0}
	 */
	SetScaleValue(t) {
		/**
		 * {
			 enable:true/false,
			 near:0,//最近
			 far:0,//最起
			 rxMin:0,//翻转角度
			 rxMax:0
			}
		 */
		this.hInEvent("SetScaleValue", t);
	}


	/**测量开关
	 * @param {Object} enable true:开启，false:关闭
	 */
	SetRule(enable) {
		console.log("测量:", enable);
		this.hInEvent("SetRule", enable);
	}

	/**----------场景飞行------------*/
	/**场景飞行
	 * @param {Boolean} enable true:开始，false:结束
	 */
	SetSceneFly(enable) {
		this.hInEvent("SetDlRun", enable);
	}

	/**设置飞行速度
	 * @param {Number} speed  
	 */
	SetSceneFlySpeed(speed) {
		this.hInEvent("SetDlSpeed", speed);
	}
	/**暂停，继续
	 * @param {Boolean} pause
	 */
	SetSceneFlyPaush(pause) {
		this.hInEvent("SetDlPause", pause);
	}

	//*********-------电梯-------**********
	OnLifts(lifts) {

	}
	GetLift() {
		this.hInEvent("GetLift", "", "OnLifts");
	}
	OnLiftRelPos(liftpos) {
		console.log("OnLiftRelPos", liftpos);
		var lift = [liftpos]; // eval("[" + liftpos + "]");
		var rectb = document.body.getBoundingClientRect();
		var fixed = lift.map(t => {
			t.pos.y = rectb.height - t.pos.y;
			t.pos.z = 10000 - Math.ceil(t.pos.z); //控制图标层级z-index
			return t;
		});
	}
	//设置电梯运行
	SetLiftRun(lift) {
		// {
		// 	gId,
		// 	toFlo,
		// 	highlighted
		// }

		this.hInEvent("SetLiftRun", lift);
	}
	//电梯高亮状态
	SetLiftState(highlighted) {
		this.hInEvent("SetLiftState", highlighted);
	}

	//*********-------车闸-------**********
	SetVehiclePassingInfo(info) {
		// {
		// 	gId,// dat.ID
		// 	plateNo,//车牌号
		// 	pass，// 进/出
		// }
		this.hInEvent("SetVehiclePassingInfo", info);
	}

	//================----------楼宇-----------==================
	/**设置转向当前视口
	 * @param {Object} v
	 * 使用通过调用 GetCurentBuildPos 返回的对象
	 */
	SetView(v) {
		/*
		{
			m_Pos: {x: 0,y: 0,z: 0},
			m_Rot: {x: 0,y: 0,z: 0}
		}
		*/
		this.hInEvent("SetView", v);
		Console.log("SetView:我在測試這個命令", v);
	}

	/**获取设置使用当前视角
	 * 
	 */

	GetCurentBuildPos() {
		this.hInEvent("GetCurentBuildPos", "", "OnCurentBuildPos");
		console.log("GetCurentBuildPos获取当前的楼宇");
	}
	/**当前视角信息
	 * @param {Object} posinfo
	 */
	OnCurentBuildPos(posinfo) {
		//当前楼宇方位
		//m_bName "bname"		
		//m_Pos x:y:z
		//m_Rot x:y:z
		var pinfo = posinfo;
		if (typeof(pinfo.m_use) == 'undefined') {
			pinfo.m_use = true;
		}
		console.log("当前建筑初始化坐标:", pinfo);
		//this.SetCurrentBuildPos(pinfo);
	}
	/**设置楼宇最佳视口
	 * @param {Object} posinfo 
	 */
	SetCurrentBuildPos(posinfo) {
		if (typeof(posinfo.m_use) == 'undefined') {
			posinfo.m_use = true;
		}
		//m_bName "bname"
		//m_Pos {x:0,y:0,z:0}
		//m_Rot {x:0,y:0,z:0}
		//m_use  true:启用
		//		console.log("当前方位", posinfo);
		this.hInEvent("SetCurrentBuildPos", posinfo);

	}
	/**转到指定楼宇
	 * @param {Object} bname
	 */
	SetBuild(bname) {
		//bname  = this._builds[n]
		this.hInEvent("SetCurrentBuild", '');

	}

	/**设置显示楼层
	 * @param {Object} flors
	 */
	SetCurrentFloors(flors) {
		//.设置显示楼层 .5半层   [-1,1,2...]
		console.log("SetCurrentFloors:", flors);
		this.hInEvent("SetCurrentFloors", flors);
	}

	/**楼层拉伸
	 * @param {Object} s
	 */
	SetFloorSpace(s) {
		//.拉伸 楼层间隔累加（米）    显示楼层小于2层时拉伸无效果
		//console.log("SetFloorSpace:", s);
		this.hInEvent("SetFloorSpace", s);
	}

	/**墙体可见设置
	 * @param {Object} s 显示(true)/隐藏(false) 
	 */
	SetWallVisible(s) {

		//console.log("SetWallVisible:", s);
		this.hInEvent("SetWallVisible", s);
	}

	/**透明度设置
	 * @param {Object} f
	 */
	SetOpacity(f) {
		//透视 f 范围【0-100】
		//console.log("SetOpacity:", f);
		this.hInEvent("SetOpacity", f + '');

	}


	//-================----------设备---------=================
	/**设备定位飞行
	 * @param {Object} idOrDat {
			ID: 0, 			//设备DatMod.ID m_dat.ID  
			scondes:0, 		//秒（s）持续时间 -1 常亮   默认5
			height:5, 		//高度 默认5
			distance:5,     //距离 默认5
		}
	 */
	FlyTo(idOrDat) {
		console.log("FlyTo:", idOrDat);
		this.hInEvent("FlyTo", idOrDat);
	}

	/**设置设备的高亮状态--根据类型
	 * @param {Object} dat
	 */
	SetDevState(dat) {
		//设置设备高亮状态， 
		//dat:{
		//  enable:false,// true:开  false:关
		//	typeId:-1, //主类型
		//	modelType:-1 //子类型
		//}
		this.hInEvent("SetStateByTypeId", dat);
	}

	/**设置设备的高亮状态--根据ID
	 * @param {Object} dat
	 */
	SetDevState2(dat) {
		//根据ID 设置 高亮状态
		//dat:
		// {
		// 	enable: true //   true:开启  ， false:关闭			
		// 	ids: [ ...] //ID  [1,2,3,...]
		// } 
		console.log("设置高亮", dat);
		this.hInEvent("SetStateById", dat);
	}


	//====================-------监控------======================
	/**开启获取监控的实时位置
	 * @param {Object} cams
	 */
	SetCamSelectUpdate(cams) {
		console.log("实时更新选中监控的位置。");
		var ids = cams.map(t => {
			return {
				id: t.id
			};
		});
		this.hInEvent("SetCamSelectUpdateEnable", ids, "CamsLocaltionRef");

	}
	/**转平面坐标
	 * @param {Object} cams
	 */
	CamsLocaltionRef(cams) {
		//更新 
		cams = eval(cams);
		var rectb = document.body.getBoundingClientRect();
		var tmpCams = cams.map(t => {
			t.pos.y = rectb.height - t.pos.y;
			return t;
		});
	}

	/**关闭获取监控的实时位置
	 * 
	 */
	SetCamSelectUpdateDisable() {
		this.hInEvent("SetCamSelectUpdateDisable", "");
		//console.log("关闭 实时更新选中监控的位置。");
		//UpDataInCam([]);
	}

	/**当前可见监控
	 * 
	 */
	SetCamSelect() {
		console.log("监控多选,返回所有当前可见监控");
		//"CamsLocaltion"); 
		this.hInEvent("SetCamSelect", "", "_CurrentVisibleCams");
	}

	/**当前所有可见监控
	 * 
	 */
	_CurrentVisibleCams(devs) {
		/**
		 * var ids=devs.map(t=>t.id);
		 * DevRelPosByIds({enable:true,ids:ids});
		 * 
		 var fixy = eval(devs);
		var rectb = document.body.getBoundingClientRect();
		_localCams = fixy.map(t => {
			t.pos.y = rectb.height - t.pos.y;
			return t;
		});
		 */
	}

	/** 实时位置的获取----------根据设备ID
	 * @param {Object} dat
	 * @param {String} back   
	 */
	DevRelPosByIds(dat, back) {
		//开启设备实时位置的获取
		//dat:{
		//  enable:false,// true:开  false:关
		//	ids:[1,2,...] ID列表
		//}

		this.hInEvent("DeviceRelPosByIds", dat, back || "_OnDevRelPosByIds");
	}
	_OnDevRelPosByIds(devs) {
		var fixy = eval(devs);

		var rectb = document.body.getBoundingClientRect();
		_localCams = fixy.map(t => {
			t.pos.y = rectb.height - t.pos.y;
			return t;
		});
		console.log(" 所有可见设备", _localCams)

	}

	/**设备实时位置的获取----------根据设备类型
	 * @param {Object} dat
	 */
	DeviceRelPosEnable(dat) {
		//开启设备实时位置的获取
		//dat:{
		//  enable:false,// true:开  false:关
		//	 typeId:-1, //主类型
		//	 modelType:-1 //子类型
		//}

		this.hInEvent("DeviceRelPosEnable", dat, "_OnDeviceRelPos");
	}

	/**设备实时位置更新，3d到2d坐标
	 * @param {Object} devs
	 */
	_OnDeviceRelPos(devs) {
		/**
		 * devs[0]:
		 * { 
			 id:0,
			 code:'',
			 
			 //
			 pos:{x:0,y:0},
			 dat:{...}
		 * }
		 */
		let fixy;
		if (typeof(devs) != 'object') {
			fixy = eval(devs);
		} else {
			fixy = devs;
		}


		//坐标修正
		var rectb = document.body.getBoundingClientRect();
		var fixdevs = fixy.map(t => {
			t.pos.y = rectb.height - t.pos.y;
			return t;
		});
		this.OnRelPosBack(fixdevs);
		//console.log("2d pos", fixdevs);
	}
	OnRelPosBack(dps) {
		return dps;
	}

	/**监控区域显示隐藏
	 * @param {Object} v v=true 显示 ，v=false 隐藏
	 */
	SetCamArea(v) {
		this.hInEvent("SetCamArea", v);
	}

	/**楼梯数量
	 * 
	 */
	GetLouTiCount() {
		this.hInEvent("SetCamArea", '', 'OnLouTiCount');
	}
	/**楼梯数量
	 * @param {Object} count
	 */
	OnLouTiCount(count) {
		console.log("楼梯数量", count);
	}

	/**投影。。。
	 * @param {Object} enable
	 * @param {Object} domvideo
	 */
	InVideo(enable, domvideo) {
		if (!this._ctx) {
			this._ctx = document.createElement("canvas").getContext('2d');
		}
		this._ctxVideo = domvideo;
		let ctx = this._ctx;

	}

	GetImageDataBegin() {
		let v = this._ctxVideo;
		let w = v.clientWidth;
		let h = v.clientHeight;
		ctx.drawImage(v, 0, 0, w, h);
		let buffers = ctx.getImageData(0, 0, w, h);

	}

	TestBuf() {

		let len = 5 // 定义ArrayBuffer长度
		let buffer = new ArrayBuffer(len);
		let dataView = new DataView(buffer) // 创建视图
		dataView.setUint8(0, Math.random() * 255) // 写入数据
		dataView.setUint8(1, Math.random() * 255)
		dataView.setUint8(2, Math.random() * 255)
		dataView.setUint8(3, Math.random() * 255)
		dataView.setUint8(4, Math.random() * 255)
		let bufs = new Int8Array(5);
		bufs[0] = 25;
		window.bufs = bufs;
		this._gameInstance.SendMessage("WebGL", "OnGetBufs");
		//__vStore.state.scene3d._gameInstance.SendMessage("WebGL", "OnGetBufs");
	}

	//=============-----------移动，旋转，缩放-------======================- 
	SetMove(xz) {
		console.log("move:", xz);
		this.hInEvent("SetMove", xz);
	}
	SetRotate(xy) {
		console.log("rot:", xy);
		this.hInEvent("SetRotate", xy);
	}
	SetScale(s) {
		console.log("scale:", s);
		this.hInEvent("SetScale", s);
	}

	//============----------漫游--------------============
	SetEye(s) {
		//漫游开关 true开始， false结束
		console.log("SetEye:", s);
		this.hInEvent("SetEye", s + '');
	}
	//弃用
	SetEyeMove(s) {
		//{x:0,y:0} float
		//console.log("move:", s);
		this.hInEvent("SetEyeMove", s);
	}
	SetEyeHeight(s) {
		//s float//漫游时高度
		console.log("eyeheight:", s);
		this.hInEvent("SetEyeHeight", s);
	}
	/**
	 * @param {Object} s 跳起高度
	 */
	SetJump(s) {
		//s float
		console.log("跳起:", s);
		this.hInEvent("SetJump", s);
	}
	SetSpeed(v) {
		console.log("速度:", v);
		this.hInEvent("SetSpeed", v);
	}

	/**运动方向
	 * @param {Object} d enable:true,k:''
	 *  w = "w", s = "s", a = "a", d = "d", space = "space", esc = "escape";
	 */
	SetDir(v) {
		this.hInEvent("SetDir", v);
	}

	/**
	 * @param {Object} d
	 * {
		 id:0 ,   //ID
		 edit: 0, //贴花投影位置设置 1:move,2:scale，3：rotate,other:end
		 code: , //配置码
	 }
	 */
	CamDecal(d, needback = true) {
		this.hInEvent("CamDecal", d, needback ? 'OnCamDecl' : '');
	};

	/**开始设置 双击默认项
	 * @param {Object} d {
		 dbtypes:['',''], // Video:前端播放，Decal:投影播放
		 currDb:            //当前播放方式
	 }
	 */
	OnCamDecl(d) {

	};

	/**
	 * @param {r:{x:0,y:0,z:0},p:{x,y,z},s:{x,y,z}} rps
	 */
	OnCamDecalChange(rps) {

	};

	/**保存配置
	 * @param {id:0,code:dbtype} d  code:播放方式
	 */
	CamDecalSaveCfg(d) {
		this.hInEvent("CamDecalSaveCfg", d, "OnCamDecalSaveCfg");
	};

	/**
	 * @param {Object} sql
	 */
	OnCamDecalSaveCfg(sql) {
		//console.log("保存投影设置 :", sql);
		this.hApiGetUpdata(sql, (t) => {
			this._elMsg.success("投影设置完成" + t.msg);
			console.log("投影设置完成 :", sql);
		});
	};

	decalObjs = {};
	CamDecalStart(d) {
		let k = `v1_v1_-1` // `v1_v1_${d.id}`;
		let v = document.getElementById(k);
		if (!v) {
			setTimeout(() => {
				this.CamDecalStart(d);
			}, 1000);
			return;
		}
		this.decalObjs[k] = {
			domId: k,
			domVideo: v,
			ctx: null,
			canv: null,
		};
		this.hInEvent("CamDecalStart", d);
	}
	CamDecalStop(d) {
		this.hInEvent("CamDecalStop", d);
	}

	hDraw(obj) {
		let w = obj.domVideo.clientWidth;
		let h = obj.domVideo.clientHeight;
		let canv = obj.canv;
		let ctx = obj.ctx;
		if (!ctx) {
			canv = document.createElement("canvas");
			canv.style = `width:${w}px;height:${h}px;`;
			canv.width = w;
			canv.height = h;
			ctx = canv.getContext('2d', {
				willReadFrequently: true
			});
			obj.canv = canv;
			obj.ctx = ctx;
			//document.body.appendChild(canv);
		}
		if (w != canv.clientWidth) {
			canv.style = `width:${w}px;height:${h}px;`;
			canv.width = w;
			canv.height = h;
		}
		ctx.drawImage(obj.domVideo, 0, 0, w, h);
		return canv;
	};
	hGetBase64(id) {
		let obj = this.decalObjs[`v1_v1_-1`]; // this.decalObjs[`v1_v1_${id}`];

		if (obj == null || !obj.domVideo) {
			return '';
		}
		let canv = this.hDraw(obj);
		return canv.toDataURL("image/jpeg", 1).replace('data:image/jpeg;base64,', '');
	}
};
function hStringToArrayBuffer(str) {
	var bytes = new Array();
	var len, c;
	len = str.length;
	for (var i = 0; i < len; i++) {
		c = str.charCodeAt(i);
		if (c >= 0x010000 && c <= 0x10FFFF) {
			bytes.push(((c >> 18) & 0x07) | 0xF0);
			bytes.push(((c >> 12) & 0x3F) | 0x80);
			bytes.push(((c >> 6) & 0x3F) | 0x80);
			bytes.push((c & 0x3F) | 0x80);
		} else if (c >= 0x000800 && c <= 0x00FFFF) {
			bytes.push(((c >> 12) & 0x0F) | 0xE0);
			bytes.push(((c >> 6) & 0x3F) | 0x80);
			bytes.push((c & 0x3F) | 0x80);
		} else if (c >= 0x000080 && c <= 0x0007FF) {
			bytes.push(((c >> 6) & 0x1F) | 0xC0);
			bytes.push((c & 0x3F) | 0x80);
		} else {
			bytes.push(c & 0xFF);
		}
	}
	var array = new Int8Array(bytes.length);
	for (var i = 0; i <= bytes.length; i++) {
		array[i] = bytes[i];
	}
	return array.buffer;
}

function hArrayBufferToString(buffer) {
	return String.fromCharCode.apply(null, new Uint8Array(buffer))
}

function Uint8ArrayToString(fileData) {
	var dataString = "";
	for (var i = 0; i < fileData.length; i++) {
		dataString += String.fromCharCode(fileData[i]);
	}
	return dataString;
}


function hTest() {
	let array = [1, 55, 49];
	let str = hArrayBufferToString(array);
	__vStore.state.scene3d._gameInstance.SendMessage("WebGL", "OnGetBufs", str);
};
var ctx = null;
var canv = null;

function hDraw(v) {
	let w = v.clientWidth;
	let h = v.clientHeight;
	if (!ctx) {
		canv = document.createElement("canvas");

		canv.width = w;
		canv.height = h;
		canv.style = `width:${w}px;height:${h}px;`;
		ctx = canv.getContext('2d', {
			willReadFrequently: true
		});
		//document.body.appendChild(canv);
	}
	if (w != canv.clientWidth) {
		canv.width = w;
		canv.height = h;
		canv.style = `width:${w}px;height:${h}px;`;
	}
	ctx.drawImage(v, 0, 0, w, h);
}

function hTestVideo(v) {
	hDraw(v);
	let w = v.clientWidth;
	let h = v.clientHeight;

	let img = ctx.getImageData(0, 0, w, h);
	let str = Uint8ArrayToString(img.data);
	__vStore.state.scene3d._gameInstance.SendMessage("WebGL", "SetTexBuffs", str);

}

function hTestVideo2(domVideo) {
	clearTimeout(t);
	hDraw(domVideo);

	let str = canv.toDataURL("image/jpeg", 1);
	__vStore.state.scene3d._gameInstance.SendMessage("WebGL", "SetTexBase64", str);

	if (interval != -1) {

		t = setTimeout(function() {
			hTestVideo2(v);
		}, interval);
	}

}


var domVideo;

function hDecalStart() {
	__vStore.state.scene3d.CamDecalStart({
		id: 21104
	});
}

function hDecalStop() {
	__vStore.state.scene3d.CamDecalStop({
		id: 21104
	})
}


function hPlay() {
	PlayVideo('-1', '-1', '192.168.1.252:8083');

	if (!domVideo) {
		domVideo = document.getElementById("v1_v1_-1")
	}
	hDraw(domVideo);
}

function hPos() {
	__vStore.state.scene3d.CamDecal({
		id: 21104,
		edit: 1
	})
}

function hScale() {
	__vStore.state.scene3d.CamDecal({
		id: 21104,
		edit: 2
	})
}

function hRot() {
	__vStore.state.scene3d.CamDecal({
		id: 21104,
		edit: 3
	})
}



//__vStore.state.scene3d.CamDecal({id:21104,edit:1,base64:''})
